// Wigets.c
#ifndef		WIDGETS_C
#define		WIDGETS_C

#include 	"Widgets.h"


struct sEvent eventDraw = {EVENT_SRC_UI, EVENT_TP_DRAW, 0, 0};
struct sEvent *WIDGET_EVENT_DRAW = &eventDraw;

uint8_t WidgetAdd( struct sWidget *pWidget, struct sWidget *pNew ){
	return NodeAdd( &pWidget->node, &pNew->node );
}	

uint8_t WidgetDel( struct sWidget *pWidget, struct sWidget *pOld ){
	return NodeDel( &pWidget->node, &pOld->node );
}	

uint8_t WidgetMove( struct sWidget *pWidget, struct sWidget *pMove ){
	return NodeMove( &pWidget->node, &pMove->node );
}	

uint8_t	WidgetEventContainer( struct sWidget *pWidget, struct sEvent *pEvent ){
	if( EVENT_SRC_UI == pEvent->src && EVENT_TP_DRAW == pEvent->type ){
		GLCDsRect( pWidget->pGLCD, pWidget->rect, GLCD_FILL, GLCD_COLOR_WHITE );
		GLCDsRect( pWidget->pGLCD, pWidget->rect, GLCD_NO_FILL, GLCD_COLOR_BLACK );
		return 1;
	}else if( EVENT_SRC_KEYB == pEvent->src && EVENT_TP_RELEASE == pEvent->type && 'A' == pEvent->data1 ){
		// Next Widget
		return 1;
	}else if( EVENT_SRC_KEYB == pEvent->src && EVENT_TP_HOLD == pEvent->type && 'A' == pEvent->data1 ){
		// Next Screen
		return 1;
	}else if( EVENT_SRC_KEYB == pEvent->src && EVENT_TP_RELEASE == pEvent->type && 'C' == pEvent->data1 ){
		// Prev Widget
		return 1;
	}else if( EVENT_SRC_KEYB == pEvent->src && EVENT_TP_HOLD == pEvent->type && 'C' == pEvent->data1 ){
		// Prev Screen
		return 1;
	}else if( EVENT_SRC_TOUCH == pEvent->src && EVENT_TP_PRESS == pEvent->type ){
	//	struct sPoint point = { pEvent->data1, pEvent->data2 };
	//	if( 0/*isInside( pWidget->rect, point )*/ ){
	//		// FocusGain();
	//		return 1;
	//	}else{
	//		return 0;
	//	}
	}
	return 0;
}

uint8_t	WidgetEventButton( struct sWidget *pWidget, struct sEvent *pEvent ){
	struct sWidgetButton *pWidgetBtn = (struct sWidgetButton*)pWidget;
	if( EVENT_SRC_UI == pEvent->src && EVENT_TP_DRAW == pEvent->type ){
		GLCDsRect( pWidget->pGLCD, pWidget->rect, GLCD_FILL, GLCD_COLOR_WHITE );
		GLCDsRect( pWidget->pGLCD, pWidget->rect, GLCD_NO_FILL, GLCD_COLOR_BLACK );
		if( WidgetFlagTest( pWidget, WIDGET_FL_PRESSED ) ){
			GLCDsRect( pWidget->pGLCD, pWidget->rect, GLCD_FILL, GLCD_COLOR_BLACK );
		}
		struct sPoint p;
		p.x = pWidget->rect.x;
		p.y = pWidget->rect.y;
		//GLCDsDrawBMP( pWidget->pGLCD, pWidgetBtn->pBMP, p );	
		GLCDsText( pWidget->pGLCD, pWidgetBtn->pFont, pWidgetBtn->pStr, p, GLCD_NO_INVERT, GLCD_NO_FILL, GLCD_COLOR_BLACK );
		return 1;
	}

	if( WidgetFlagTest( pWidget, WIDGET_FL_PRESSED ) ){
		if( EVENT_SRC_KEYB == pEvent->src && EVENT_TP_RELEASE == pEvent->type && 'B' == pEvent->data1 ){
			WidgetFlagClear( pWidget, WIDGET_FL_PRESSED );
			WidgetEventButton( pWidget, WIDGET_EVENT_DRAW );
			return 1;
		}
	}else{
		if( EVENT_SRC_KEYB == pEvent->src && EVENT_TP_PRESS == pEvent->type && 'B' == pEvent->data1 ){
			WidgetFlagSet( pWidget, WIDGET_FL_PRESSED );
			WidgetEventButton( pWidget, WIDGET_EVENT_DRAW );
			if( NULL != pWidgetBtn->pCBPress ){
				 pWidgetBtn->pCBPress( pWidgetBtn );
			}
			return 1;
		}
	}
	return 0;
}


uint8_t WidgetEventID( struct sWidget *pWidget, struct sEvent *pEvent ){
	switch( pWidget->ID ){
		case WIDGET_ID_CONTAINER:	return WidgetEventContainer( pWidget, pEvent );
//		case WIDGET_ID_TEXT: 		return WidgetEventText( pWidget, pEvent );
		case WIDGET_ID_BUTTON: 		return WidgetEventButton( pWidget, pEvent );
		default: return 0;
	}
	return 0;
}

uint8_t	WidgetEvent( struct sWidget *pWidget, struct sEvent *pEvent ){
	if( pWidget == NULL ){
		return 0;
	}	
	if( EVENT_SRC_UI == pEvent->src ){
		WidgetEventID( pWidget, pEvent );
		WidgetEvent( (struct sWidget*)pWidget->node.pChild, pEvent );
		WidgetEvent( (struct sWidget*)pWidget->node.pNext, pEvent );
		return 1;
	}else{
		if( WidgetEvent( (struct sWidget*)pWidget->node.pNext, pEvent ) ){
			return 1;
		}
		if( WidgetEvent( (struct sWidget*)pWidget->node.pChild, pEvent ) ){
			return 1;
		}
	
		if( WidgetEventID( pWidget, pEvent ) ){
			return 1;
		}	
	}
	return 0;
}

//uint8_t WidgetEventText( struct sWidget *pWidget, struct sEvent *pEvent );

uint8_t WidgetEventButton( struct sWidget *pWidget, struct sEvent *pEvent );

// Widgets flags test/change
uint8_t	WidgetFlagTest( struct sWidget *pWidget, uint16_t flag ){
	return (0 != (pWidget->flags & flag) );
}

void	WidgetFlagSet( struct sWidget *pWidget, uint16_t flag ){
	pWidget->flags |= flag;
	return;
}

void	WidgetFlagClear( struct sWidget *pWidget, uint16_t flag ){
	pWidget->flags &= ~flag;
	return;
}

void	WidgetFlagToggle( struct sWidget *pWidget, uint16_t flag ){
	pWidget->flags ^= flag;
	return;
}

// Widgets navigation


#define		WIDGET_MAIN_TEST	1
#ifdef		WIDGET_MAIN_TEST

#include <stdio.h>
#include	"P24FJ64GA004.h"
#include	"WidgetsUI.h"

uint8_t myGLCDBuffer[(GLCD_WIDTH*GLCD_HEIGHT) / 8];

struct sGLCD myGLCD = {
    GLCD_WIDTH, GLCD_HEIGHT,
    myGLCDBuffer,
    {
        {
            { 7, &PORTA, &TRISA, &LATA},
            { 0, &PORTA, &TRISA, &LATA},
            { 2, &PORTA, &TRISA, &LATA},
            { 1, &PORTA, &TRISA, &LATA},
            { 0, &PORTC, &TRISC, &LATC}
        },
        {
            { 8, &PORTA, &TRISA, &LATA},
            { 0, &PORTA, &TRISA, &LATA},
            { 2, &PORTA, &TRISA, &LATA},
            { 1, &PORTA, &TRISA, &LATA},
            { 0, &PORTC, &TRISC, &LATC}
        }
    }
};


struct sPin sPinLed;
struct sPin sPinBtnA;
struct sPin sPinBtnB;
struct sPin sPinBtnC;

struct sPin sPinLed = {
	3,
	&PORTB, &TRISB, &LATB
};

struct sPin sPinBtnA = {
	3,
	&PORTA, &TRISA, &LATA
};

struct sPin sPinBtnB = {
	9,
	&PORTA, &TRISA, &LATA
};

struct sPin sPinBtnC = {
	10,
	&PORTA, &TRISA, &LATA
};


#define		BUTTON_HOLD_TIME	1000
int main(void) {
	uint32_t timer = 0;
	
	uint8_t BtnA = 0, BtnB = 0, BtnC = 0;
	uint8_t BtnABck = 0, BtnBBck = 0, BtnCBck = 0;
	uint32_t BtnATimer = 0, BtnBTimer = 0, BtnCTimer = 0;
	
	struct sEvent event = {0,0};
	struct sWidget *pWidgetTop = (struct sWidget*)&Cont1;
	
	WidgetAdd( (struct sWidget*)&Cont1, (struct sWidget*)&Button1 );
	WidgetAdd( (struct sWidget*)&Cont1, (struct sWidget*)&Button2 );
	WidgetAdd( (struct sWidget*)&Cont1, (struct sWidget*)&Button3 );
	
    if (GLCDOpen(&myGLCD)) {
        return -1; // Can't open LCD
    }

	PinOpen( &sPinLed, PIN_OUTPUT, PIN_LOW );
	PinOpen( &sPinBtnA, PIN_INPUT, PIN_LOW );
	PinOpen( &sPinBtnB, PIN_INPUT, PIN_LOW );
	PinOpen( &sPinBtnC, PIN_INPUT, PIN_LOW );

//	WidgetDraw( pWidgetTop );
	WidgetEvent( pWidgetTop, WIDGET_EVENT_DRAW );
	GLCDRefresh( &myGLCD );

	while(1){

		if( 0 == (timer++ & 0x00000FFF) ){
//			sEvent.eSource = EVENT_SRC_TIMER;
//			sEvent.eType = EVENT_TP_TIMER_TICK;
//			WidgetEvent( pWidgetTop, &sEvent );
			GLCDRefresh( &myGLCD );
		}

		BtnABck = BtnA;
		BtnBBck = BtnB;
		BtnCBck = BtnC;

		BtnA = PinRead( &sPinBtnA );	
		BtnB = PinRead( &sPinBtnB );	
		BtnC = PinRead( &sPinBtnC );	
		
		if( !BtnABck && BtnA ){
			BtnATimer = timer;
			event.src = EVENT_SRC_KEYB;
			event.type = EVENT_TP_PRESS;
			event.data1 = 'A';
			WidgetEvent( pWidgetTop, &event );
		}else if( BtnABck && BtnA ){
			if( timer - BtnATimer == BUTTON_HOLD_TIME ){
				event.src = EVENT_SRC_KEYB;
				event.type = EVENT_TP_HOLD;
				event.data1 = 'A';
				WidgetEvent( pWidgetTop, &event );
			}
		}else if( BtnABck && !BtnA ){
			event.src = EVENT_SRC_KEYB;
			event.type = EVENT_TP_RELEASE;
			event.data1 = 'A';
			WidgetEvent( pWidgetTop, &event );
		}
		
		if( !BtnBBck && BtnB ){
			BtnBTimer = timer;
			event.src = EVENT_SRC_KEYB;
			event.type = EVENT_TP_PRESS;
			event.data1 = 'B';
			WidgetEvent( pWidgetTop, &event );
		}else if( BtnBBck && BtnB ){
			if( timer - BtnBTimer == BUTTON_HOLD_TIME ){
				event.src = EVENT_SRC_KEYB;
				event.type = EVENT_TP_HOLD;
				event.data1 = 'B';
				WidgetEvent( pWidgetTop, &event );
			}
		}else if( BtnBBck && !BtnB ){
			event.src = EVENT_SRC_KEYB;
			event.type = EVENT_TP_RELEASE;
			event.data1 = 'B';
			WidgetEvent( pWidgetTop, &event );
		}
				
		if( !BtnCBck && BtnC ){
			BtnCTimer = timer;
			event.src = EVENT_SRC_KEYB;
			event.type = EVENT_TP_PRESS;
			event.data1 = 'C';
			WidgetEvent( pWidgetTop, &event );
		}else if( BtnCBck && BtnC ){
			if( timer - BtnCTimer == BUTTON_HOLD_TIME ){
				event.src = EVENT_SRC_KEYB;
				event.type = EVENT_TP_HOLD;
				event.data1 = 'C';
				WidgetEvent( pWidgetTop, &event );
			}
		}else if( BtnCBck && !BtnC ){
			event.src = EVENT_SRC_KEYB;
			event.type = EVENT_TP_RELEASE;
			event.data1 = 'C';
			WidgetEvent( pWidgetTop, &event );
		}

	}

	GLCDClose( &myGLCD );
	while(1);

    return 0;
}

#endif		//#ifdef	WIDGET_MAIN_TEST

#endif		//#ifndef		WIDGETS_C
